/* Gunslinger - A Shamir's Secret Sharing system.
 *
 * Program that implements the Shamir's Secret Sharing system.
 * http://en.wikipedia.org/wiki/Shamir%27s_Secret_Sharing
 *
 * Usage :
 *
 * To split -
 * 		gs -split secret n t
 * where
 * 		secret is the number that is to be split
 *		n is the number of parts the secret is to be split
 *		t is the minimum number of parts required to
 *			rebuild the secret.
 *
 * To rebuild -
 *		gs -rebuild part1 part2 part3 ... partn
 * where
 *		part1 part2 part3 and partn are the parts
 *		that would rebuild the secret.
 */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>

void throwUsageError();
void splitSecret(int argc, char *argv[]);
void rebuildSecret(int argc, char *argv[]);
int rand100(void);
void prepCoeffs(int[], long int, int);
int subInPolynomial(int[], int, int);
int power(int,int);

//start of program
main(int argc, char *argv[]){
	if(argc > 2){
		if(strcmp(argv[1],"-split")==0){
			splitSecret(argc, argv);
		} else if(strcmp(argv[1],"-rebuild")==0){
			rebuildSecret(argc, argv);
		} else {
			throwUsageError();
		}
	} else {
		throwUsageError();
	}
}

//function to print the usage format incase of incorrect usage.
void throwUsageError(){

	printf("\t[Usage]\n");
	printf("\tTo split\n");
	printf("\t\tgs -split secret n t\n");
	printf("\tTo rebuild\n");
	printf("\t\tgs -rebuild part1 part2 part3 ... partn\n");
}

//function that handles splitting
void splitSecret(int argc, char *argv[]){
	printf("splitSecret\n");
	if(argc!=5){
		printf("Some arguments missing for splitting secret.\n");
		throwUsageError();
		return;
	}
	long int secret = atoi(argv[2]);
	printf("secret - %lu\n", secret);
	short int n = atoi(argv[3]);
	short int t = atoi(argv[4]);
	printf("n t %d %d\n",n,t);
	if(t > n){
		printf("Minimum parts 't' cannot be greater than total parts 'n'.\n");
		throwUsageError();
		return;
	}

	int coeffs[t];		//array to hold the coefficients of the t-1 degree poly.
	int parts[n];		//array to hold the final parts
	int randComp[n];	//array to store the random input component of each part.
	int i,j;
	
	//create a seed (time(NULL)) and use it for new random number generation
	srand(time(NULL));

	//prepare coefficients for t-1 degree polynomial
	prepCoeffs(coeffs, secret,t);

	//Loop n times for n parts.
	for(i=0;i<n;i++){
		//Get a random number between 1 and 100
		randComp[i]=rand100();
		parts[i] = subInPolynomial(coeffs, t, randComp[i]);
	}

	//print the parts
	printf("Parts - \n");
	for(i=0;i<n;i++){
		printf("%d-%d\t", randComp[i], parts[i]);
	}
	putchar('\n');
}

void prepCoeffs(int coeffs[], long int secret, int t){

	int i;

	//The first coefficient is the secret according to the scheme
	coeffs[0]=secret;

	for(i=1;i<t;i++){
		coeffs[i]=rand100();
		printf("coeffs %d %d\n",i,coeffs[i]);
	}
}

//function that handles rebuilding
void rebuildSecret(int argc, char *argv[]){
	printf("rebuildSecret\n");
}

//substitutes the value of x in the polynomial
int subInPolynomial(int coeffs[], int degree, int x){
	int i;
	int sum=0;
	for(i=0;i<degree;i++){
		sum = sum + coeffs[i] * power(x,i);
	}
	return sum;
}

//get a random number from 1 to 100
int rand100(void){
	return rand() % 100;
}

int power(int x, int y){
	if(y==0){
		return 1;
	}
	int i;
	int mul = 1;

	for(i=0;i<y;i++){
		mul = mul * x;
	}
	return mul;
}

//Features to add
// - enter secret as text. convert to number. - use atoi or atol from stdlib
